/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2006，所有权利保留。
 * 
 * 文件名：	BOrganizationMgr.java
 * 模块说明：	
 * 修改历史：
 * 2006-4-28 - lxm - 创建。
 */
package com.hd123.rumba.organization.biz;

import java.util.ArrayList;
import java.util.List;

import net.sf.hibernate.Hibernate;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.type.Type;

import com.hd123.rumba.domain.IDomainMgr;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.gwt.base.client.biz.BPersistent;
import com.hd123.rumba.organization.COrganization;
import com.hd123.rumba.organization.IOrganization;
import com.hd123.rumba.organization.IOrganizationMgr;
import com.hd123.rumba.runtime.IManager;
import com.hd123.rumba.runtime.NamingMgr;
import com.hd123.rumba.runtime.OperateContext;
import com.hd123.rumba.runtime.biz.BManager;
import com.hd123.rumba.sql.HibernateSelect;
import com.hd123.rumba.sql.SCE;
import com.hd123.rumba.sql.SQLSubquery;
import com.hd123.rumba.sql.SelectExecutor;
import com.hd123.rumba.user.IUser;
import com.hd123.rumba.util.ClassifiedHashtable;

/**
 * 组织 | 业务层 | 管理员 | 实现类
 * 
 * @author lxm
 * 
 */
public class BOrganizationMgr extends BManager implements IBOrganizationMgr {

  private IOrganizationMgr porgMgr = null;

  public IManager getPerzMgr() throws BusinessException {
    return getOrgMgr();
  }

  public BOrganization createOrganization(String upperOrgUuid) throws BusinessException,
      HibernateException {
    IDomainMgr domainMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    BOrganization borg = new BOrganization();
    if (upperOrgUuid != null) {
      IOrganization upperOrg = getOrgMgr().getOrganization(upperOrgUuid);
      if (upperOrg == null)
        throw new BusinessException("找不到指定的" + COrganization.CAPTION_UPPERORGANIZATION + "\""
            + upperOrgUuid + "\"。");
      if (COrganization.VALUE_STATE_DELETED.equals(upperOrg.getState()))
        throw new BusinessException("指定的" + COrganization.CAPTION_UPPERORGANIZATION + "\""
            + upperOrg.getCodeName() + "\"已经被删除。");

      borg.getDomain().readFrom(domainMgr.getRootDomain());
      borg.setUpperOrganization(new SOrganization());
      borg.getUpperOrganization().readFrom(upperOrg);
    } else {
      borg.getDomain().readFrom(domainMgr.getRootDomain());
      borg.setUpperOrganization(null);
    }
    borg.setState(COrganization.VALUE_STATE_USING);
    return borg;
  }

  public BOrganization loadOrganization(String uuid) throws BusinessException, HibernateException {
    checkParameterNotNull(uuid, "uuid");

    IOrganization org = getOrgMgr().getOrganization(uuid);
    BOrganization borg = null;
    if (org != null) {
      borg = new BOrganization();
      borg.readFrom(org);
    }
    return borg;
  }

  /** @deprecated */
  public ClassifiedHashtable saveOrganizationT(BOrganization org, IUser operator)
      throws BusinessException, HibernateException {
    return this.saveOrganizationT(org, new OperateContext(operator));
  }

  public ClassifiedHashtable saveOrganizationT(BOrganization org, OperateContext operate)
      throws BusinessException, HibernateException {
    checkParameterNotNull(org, "org");
    checkParameterNotNull(operate, "operate");

    IOrganization porg = createOrLoadPOrganization(org);
    ClassifiedHashtable h = verifyToSave(org, porg);
    if (h != null)
      return h;
    writeTo(org, porg);

    Transaction tx = getSession().beginTransaction();
    try {
      getOrgMgr().saveOrganization(porg, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }

    org.readFrom(porg);
    return null;
  }

  /** @deprecated */
  public boolean deleteOrganizationT(String orgUuid, IUser operator, long oca)
      throws BusinessException, HibernateException {
    return this.deleteOrganizationT(orgUuid, new OperateContext(operator), oca);
  }

  public boolean deleteOrganizationT(String orgUuid, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    this.checkParameterNotNull(orgUuid, "orgUuid");
    this.checkParameterNotNull(operate, "operate");
    IOrganization porg = getOrgMgr().getOrganization(orgUuid);
    if (COrganization.VALUE_STATE_DELETED.equals(porg.getState()))
      return false;
    ClassifiedHashtable h = verifyToDelete(porg, operate, oca);
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    Transaction tx = getSession().beginTransaction();
    try {
      getOrgMgr().deleteOrganization(porg, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }
    return true;
  }

  /** @deprecated */
  public boolean undeleteOrganizationT(String orgUuid, IUser operator, long oca)
      throws BusinessException, HibernateException {
    return this.undeleteOrganizationT(orgUuid, new OperateContext(operator), oca);
  }

  public boolean undeleteOrganizationT(String orgUuid, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    IOrganization porg = getOrgMgr().getOrganization(orgUuid);
    if (COrganization.VALUE_STATE_USING.equals(porg.getState()))
      return false;
    ClassifiedHashtable h = verifyToUndelete(porg, operate, oca);
    if (h != null)
      throw new BusinessException(h.getAllMessages());

    Transaction tx = getSession().beginTransaction();
    try {
      getOrgMgr().undeleteOrganization(porg, operate);
      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      throw new BusinessException(e);
    } finally {
      getSession().flush();
    }
    return true;
  }

  public SOrganization getOrganization(String uuid) throws BusinessException, HibernateException {
    SOrganization sorg = null;
    IOrganization org = getOrgMgr().getOrganization(uuid);
    if (org != null) {
      sorg = new SOrganization();
      sorg.readFrom(org);
    }
    return sorg;
  }

  public <T extends BPersistent> T getOrganization(String uuid, Class<T> bizClass)
      throws BusinessException, HibernateException {
    IOrganization perz = getOrgMgr().getOrganization(uuid);
    if (perz == null)
      return null;
    T biz = this.createBizClass2(bizClass);
    this.assignPerzToBiz(perz, biz);
    return biz;
  }

  public SOrganization getOrganizationByCode(String code) throws BusinessException,
      HibernateException {
    SOrganization sorg = null;
    IOrganization org = getOrgMgr().getOrganizationByCode(code, null);
    if (org != null) {
      sorg = new SOrganization();
      sorg.readFrom(org);
    }
    return sorg;
  }

  public <T extends BPersistent> T getOrganizationByCode(String code, Class<T> bizClass)
      throws BusinessException, HibernateException {
    IOrganization perz = getOrgMgr().getOrganizationByCode(code, null);
    if (perz == null)
      return null;
    T biz = this.createBizClass2(bizClass);
    this.assignPerzToBiz(perz, biz);
    return biz;
  }

  public <T extends BPersistent> T getOrganizationByOrgDomain(String orgDomainUuid,
      Class<T> bizClass) throws BusinessException, HibernateException {
    IOrganization perz = getOrgMgr().getOrganizationByOrgDomain(orgDomainUuid);
    if (perz == null)
      return null;
    T biz = this.createBizClass2(bizClass);
    this.assignPerzToBiz(perz, biz);
    return biz;
  }

  public List<QOrganization> getLowerOrganizations(String upperOrgUuid) throws BusinessException,
      HibernateException {
    List<QOrganization> result = new ArrayList();
    List list = null;
    if (upperOrgUuid == null)
      list = getSession().find(
          "from " + IOrganization.class.getName() + " o"
              + " where o.upperOrganization is null order by o.code");
    else
      list = getSession().find(
          "from " + IOrganization.class.getName() + " o"
              + " where o.upperOrganization.uuid = ? order by o.code", upperOrgUuid,
          Hibernate.STRING);

    for (int i = 0; i < list.size(); i++) {
      QOrganization org = new QOrganization();
      org.readFrom((IOrganization) list.get(i));
      result.add(org);
    }
    return result;
  }

  public Integer getLowerOrganizationsCount(String upperOrgUuid, boolean direct)
      throws BusinessException, HibernateException {
    List list = null;
    if (direct) {
      if (upperOrgUuid == null)
        list = getSession().find(
            "select count(o) from " + IOrganization.class.getName() + " o"
                + " where o.upperOrganization is null and o.state != ?",
            COrganization.VALUE_STATE_DELETED, Hibernate.INTEGER);
      else
        list = getSession().find(
            "select count(o) from " + IOrganization.class.getName() + " o"
                + " where o.upperOrganization.uuid = ? and o.state != ?", new Object[] {
                upperOrgUuid, COrganization.VALUE_STATE_DELETED }, new Type[] {
                Hibernate.STRING, Hibernate.INTEGER });
    } else {
      if (upperOrgUuid == null)
        list = getSession().find(
            "select count(o) from " + IOrganization.class.getName() + " o" + " where o.state != ?",
            COrganization.VALUE_STATE_DELETED, Hibernate.INTEGER);
      else {
        IOrganization porg = getOrgMgr().getOrganization(upperOrgUuid);
        SQLSubquery sq = new SQLSubquery();
        sq.addSelect("count(o)");
        sq.addFrom(IOrganization.class.getName(), "o");
        sq.addWhere("o.levelId like ?", porg.getLevelId(), SQLSubquery.WC_RIGHT);
        sq.addWhere("and o.uuid != ?", upperOrgUuid);
        sq.addWhere("and o.state != ?", COrganization.VALUE_STATE_DELETED);
        SelectExecutor worker = new HibernateSelect(getSession(), sq, 0);
        list = worker.getContentList(0, 0);
      }
    }
    if (list.size() > 0)
      return (Integer) list.get(0);
    else
      return new Integer(0);
  }

  public <T extends BPersistent> List<T> getUpperOrganizations(String orgUuid, Class<T> bizClass)
      throws BusinessException, HibernateException {
    List<T> bizs = new ArrayList<T>();
    IOrganization perz = getOrgMgr().getOrganization(orgUuid);
    if (perz == null)
      throw new BusinessException("指定的" + COrganization.CAPTION_CLASS + "不存在。");
    perz = perz.getUpperOrganization();
    while (perz != null) {
      T biz = this.createBizClass2(bizClass);
      this.assignPerzToBiz(perz, biz);
      bizs.add(0, biz);
      perz = perz.getUpperOrganization();
    }
    return bizs;
  }

  public Integer getBrotherOrganizationsCount(String orgUuid) throws BusinessException,
      HibernateException {
    this.checkParameterNotNull(orgUuid, "orgUuid");
    IOrganization porg = getOrgMgr().getOrganization(orgUuid);
    List list = null;
    SQLSubquery sq = new SQLSubquery();
    sq.addSelect("count(o)");
    sq.addFrom(IOrganization.class.getName(), "o");
    if (porg.getUpperOrganization() == null)
      sq.addWhere("o.upperOrganization is null");
    else
      sq.addWhere("o.upperOrganization.uuid = ?", porg.getUpperOrganization().getUuid());
    sq.addWhere("and o.uuid != ?", orgUuid);
    sq.addWhere("and o.state != ?", COrganization.VALUE_STATE_DELETED);
    SelectExecutor worker = new HibernateSelect(getSession(), sq, 0);
    list = worker.getContentList(0, 0);
    if (list.size() > 0)
      return (Integer) list.get(0);
    else
      return new Integer(0);
  }

  public int getRelativePosition(BOrganization currOrg, BOrganization org) throws BusinessException {
    checkParameterNotNull(currOrg, "currOrg");
    checkParameterNotNull(org, "org");
    int result = VALUE_RELATIONSHIP_OTHER;
    if (org.getUuid() == null || "".equals(org.getUuid())) { // 如果org是新增的对象
      if (org.getUpperOrganization() == null) {
        if (currOrg.getUpperOrganization() == null)
          result = VALUE_RELATIONSHIP_BROTHER;
      } else {
        try {
          String currLevelId = currOrg.getLevelId();
          BOrganization upperOrg = this.loadOrganization(org.getUpperOrganization().getUuid());
          String levelId = upperOrg.getLevelId();
          if (upperOrg.equals(currOrg.getUpperOrganization()))
            return VALUE_RELATIONSHIP_BROTHER;
          else if (currLevelId.length() <= levelId.length()
              && levelId.substring(0, currLevelId.length()).equals(currLevelId))
            result = VALUE_RELATIONSHIP_LOWER;
        } catch (Exception e) {
          throw new BusinessException(e);
        }
      }
    } else {
      String currLevelId = currOrg.getLevelId();
      String levelId = org.getLevelId();
      if (currLevelId.equals(levelId))
        result = VALUE_RELATIONSHIP_SELF;
      else if (currLevelId.length() < levelId.length()
          && levelId.substring(0, currLevelId.length()).equals(currLevelId))
        result = VALUE_RELATIONSHIP_LOWER;
      else if (currLevelId.length() > levelId.length()
          && currLevelId.substring(0, levelId.length()).equals(levelId))
        result = VALUE_RELATIONSHIP_UPPER;
      else if ((currOrg.getUpperOrganization() != null && org.getUpperOrganization() != null && currOrg
          .getUpperOrganization().getUuid().equals(org.getUpperOrganization().getUuid()))
          || (currOrg.getUpperOrganization() == null && org.getUpperOrganization() == null))
        result = VALUE_RELATIONSHIP_BROTHER;
    }
    return result;
  }

  public String getOrganizationLevelId(String uuid) throws BusinessException, HibernateException {
    checkParameterNotNull(uuid, "uuid");
    IOrganization org = getOrgMgr().getOrganization(uuid);
    return org.getLevelId();
  }

  public Integer getCountOfChildren(String orgUuid, boolean direct, Integer[] states)
      throws BusinessException, HibernateException {
    SQLSubquery sq = new SQLSubquery();
    sq.addSelect("count(o)");
    sq.addFrom(IOrganization.class.getName(), "o");
    SCE cond = new SCE(SCE.VALUE_OPERATOR_AND);
    if (direct) {
      if (orgUuid == null)
        cond.append(SCE.cond("o.upperOrganization is null"));
      else
        cond.append(SCE.cond("o.upperOrganization.uuid = ?", orgUuid));
    } else {
      String levelId = this.getOrganizationLevelId(orgUuid);
      cond.append(SCE.cond("o.levelId like ?", levelId, SCE.WC_RIGHT));
    }
    if (states != null)
      cond.append(SCE.cond("o.state in ?", states));
    sq.setWhere(cond);
    SelectExecutor worker = new HibernateSelect(getSession(), sq, 0);
    List list = worker.getContentList(0, 0);
    if (list.size() > 0)
      return (Integer) list.get(0);
    else
      return new Integer(0);
  }

  /**
   * 取得持久层的组织管理员。
   * 
   * @return
   * @throws BusinessException
   */
  private IOrganizationMgr getOrgMgr() throws BusinessException {
    if (porgMgr == null)
      porgMgr = (IOrganizationMgr) NamingMgr.getInstance().lookupMgr(IOrganizationMgr.class);
    return porgMgr;
  }

  private IOrganization createOrLoadPOrganization(BOrganization org) throws BusinessException,
      HibernateException {
    IOrganization porg = null;
    IOrganization upperOrg = null;
    if (org.getUpperOrganization() != null)
      upperOrg = getOrgMgr().getOrganization(org.getUpperOrganization().getUuid());
    if (org.getUuid() == null)
      porg = getOrgMgr().createOrganization(upperOrg, org.getCode());
    else
      porg = getOrgMgr().getOrganization(org.getUuid());
    return porg;
  }

  /**
   * 将指定组织业务对象写到持久化对象中。append/update方式。
   * 
   * @param borg
   * @throws HibernateException
   * @throws BusinessException
   */
  private void writeTo(BOrganization borg, IOrganization porg) throws BusinessException {
    porg.setCode(borg.getCode());
    porg.setName(borg.getName());
    porg.setRemark(borg.getRemark());
  }

  private ClassifiedHashtable verifyToSave(BOrganization borg, IOrganization porg)
      throws BusinessException, HibernateException {
    ClassifiedHashtable h = this.checkOca(porg, borg.getOca(), COrganization.CAPTION_CLASS, porg
        .getNameCode());
    if (h != null)
      return h;

    h = new ClassifiedHashtable();

    if (borg.getCode() == null)
      borg.setCode("");
    else
      borg.setCode(borg.getCode().trim());

    if ("".equals(borg.getCode().trim())) {
      h.putMessage("code", ClassifiedHashtable.ERROR, COrganization.CAPTION_CLASS + "的"
          + COrganization.CAPTION_CODE + "不能为空。");
    } else {
      IOrganization porg2 = getOrgMgr().getOrganizationByCode(borg.getCode());
      if (porg2 != null && !porg2.getUuid().equals(borg.getUuid()))
        h.putMessage("code", ClassifiedHashtable.ERROR, "已经存在相同" + COrganization.CAPTION_CODE + "的"
            + COrganization.CAPTION_CLASS + "。");
    }

    if (borg.getUuid() != null) {
      long poca = getOrgMgr().getOrganization(borg.getUuid()).getOca();
      if (borg.getOca() != poca)
        h.putMessage("oca", ClassifiedHashtable.ERROR, "指定" + COrganization.CAPTION_CLASS
            + "已经被其他用户修改" + "，您所做的修改将被取消(" + COrganization.CAPTION_CODE + "=" + borg.getCode()
            + ")。");
    }

    if (h.size() > 0)
      return h;
    else
      return null;
  }

  private ClassifiedHashtable verifyToDelete(IOrganization porg, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    ClassifiedHashtable h = this.checkOca(porg, oca, COrganization.CAPTION_CLASS, porg
        .getNameCode());
    if (h != null)
      return h;

    return null;
  }

  private ClassifiedHashtable verifyToUndelete(IOrganization porg, OperateContext operate, long oca)
      throws BusinessException, HibernateException {
    ClassifiedHashtable h = this.checkOca(porg, oca, COrganization.CAPTION_CLASS, porg
        .getNameCode());
    if (h != null)
      return h;

    return null;
  }
}
